package cn.sdnu.database.service;

import cn.sdnu.database.controller.DbController;
import cn.sdnu.database.utils.FileCreate;
import cn.sdnu.database.utils.Utils;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Master_Joe qiaoguangtong@aliyun.com
 */
public class Create {
	private static Create create = null;
	private static ReentrantLock lock = new ReentrantLock();

	private Create() {

	}

	public static Create getInstance() {
		if (create == null) {
			lock.lock();
			try {
				if (create == null) {
					create = new Create();
				}
			} finally {
				lock.unlock();
			}
		}
		return create;
	}

	/**
	 * 处理SQL语句
	 * 
	 * @param sql 我们要处理的SQL语句
	 */
	public void sqlHandle(String sql) {
		if (sql.startsWith("create database ")) {
			// TODO 判断括号的个数
			createDatabase(sql);
		} else if (sql.startsWith("create table ")) {
			if (Use.getInstance().getDatabaseUsed() != null) {
				createTable(sql);
			} else if (Use.getInstance().getDatabaseUsed() == null) {
				System.out.println("ERROR: No database selected");
			}
		} else if (sql.startsWith("create view ")) {

		} else {
			System.out.println("Error: You have some syntax error, please try again");
		}
	}

	/**
	 * 创建表
	 * 
	 * @param sql 建表语句
	 */
	private void createTable(String sql) {
		String str = sql.substring(13, sql.length() - 2);
		int parenthesesIndex = str.indexOf("(");
		String tableName = str.substring(0, parenthesesIndex).replaceAll(" $", "");
		int parenthesesLastIndex = str.lastIndexOf(")");
		String innerText = str.substring(parenthesesIndex + 1, parenthesesLastIndex).replaceAll("^ ", "");
		String[] columnNames = innerText.split(", ");
		String[][] columns = new String[columnNames.length][3];
		// 初始化二维数组
		for (int i = 0; i < columns.length; i++) {
			for (int j = 0; j < columns[0].length; j++) {
				columns[i][j] = "";
			}
		}
		/*
		 * 赋值 列 列类型 约束条件
		 */
		for (int i = 0; i < columns.length; i++) {
			columns[i][0] = columnNames[i].split(" ")[0];
			columns[i][1] = columnNames[i].split(" ")[1];
			if (columnNames[i].split(" ").length > 2) {
				for (int j = 2; j < columnNames[i].split(" ").length; j++) {
					columns[i][2] += columnNames[i].split(" ")[j] + " ";
				}
			}
		}
		// 判断是否有重复列
		String temp = "";
		for (int i = 0; i < columns.length; i++) {
			for (int j = i + 1; j < columns.length; j++) {
				if (columns[i][0].equals(columns[j][0])) {
					temp = columns[i][0];
					break;
				}
			}
		}
		if (temp != "") {
			System.out.println("Error: Can't create table, you has the repeated column: " + temp + ";");
//			重复列处理
			return;
		}
		// 正则表达式判断类型
		String typePatten = "((INT\\(+[0-9][0-9]*+\\))|\\bINT\\b|(CHAR\\(+[0-9][0-9]*+\\))|(VARCHAR\\(+[0-9][0-9]*+\\)))";
		Pattern p = Pattern.compile(typePatten, Pattern.CASE_INSENSITIVE);
		for (int i = 0; i < columns.length; i++) {
			Matcher m = p.matcher(columns[i][1]);
			if (!m.matches()) {
				System.out
						.println("Error: You have some syntax error near the " + columns[i][1] + ", please try again");
				return;
//				break;
			}
		}
		// 判断约束条件
		List<String> constraintList = new ArrayList<String>();
		constraintList.add("primary");
		constraintList.add("key");
		constraintList.add("not");
		constraintList.add("null");
		constraintList.add("auto_increment");
		constraintList.add("unique");

		// 分解输入的条件
		List<String> inputConstraint = new ArrayList<String>();
		for (int i = 0; i < columns.length; i++) {
			if (!"".equals(columns[i][2])) {
				columns[i][2].replaceAll(" $", "");
				String[] split2 = columns[i][2].split(" ");
				for (String string : split2) {
					inputConstraint.add(string);
				}
			}
		}

		for (int i = 0; i < inputConstraint.size(); i++) {
			boolean constraintHit = false;
			if ("primary".equals(inputConstraint.get(i))) {
				if ("key".equals(inputConstraint.get(i + 1))) {
					constraintHit = true;
				}
				i++;
			} else if ("not".equals(inputConstraint.get(i))) {
				if ("null".equals(inputConstraint.get(i + 1))) {
					constraintHit = true;
				}
				i++;
			} else {
				for (int j = 4; j < constraintList.size(); j++) {
					if (inputConstraint.get(i).equals(constraintList.get(j))) {
						constraintHit = true;
						break;
					}
				}
			}
			if (!constraintHit) {
				System.out.println("Error: You have constraint error, please try again");
				return;
//				break;
			}
		}

		// 打印
		boolean saveTable = saveTable(tableName, columns);
		if (saveTable) {
			System.out.println("Query OK, 0 rows affected");
		}
	}

	/**
	 * 创建数据库
	 * 
	 * @param sql
	 */
	private void createDatabase(String sql) {
		String dbName = sql.substring(16, sql.length() - 2);

		// create a fold to stand for database;
		File file = new File(DbController.TEST_BASE + dbName + File.separator);
		if (file.exists()) {
			System.out.println("Error: Can't create database '" + dbName + "'; database exists");
		} else {
			boolean mkdir = file.mkdir();
			if (mkdir) {
				System.out.println("Query OK, 1 row affected");
			} else {
				System.out.println("Error: Can't create database '" + dbName + ";");
			}
		}
	}

	/**
	 * 保存表文件到本地
	 * 
	 * @param tableName   创建表的表明
	 * @param columnsInfo
	 * @return {@code true} 保存正常 {@code false} 保存失败
	 */
	private boolean saveTable(String tableName, String[][] columnsInfo) {

		String tablePath = DbController.TEST_BASE + Use.getInstance().getDatabaseUsed() + File.separator + tableName
				+ DbController.EXTENSION;

		List<String> tables = Utils.getTables(Use.getInstance().getDatabaseUsed());

		if (tables.contains(tableName)) {
			System.out.println("ERROR: Table '" + tableName + "' already exists");
			return false;
		}

		boolean createFile = FileCreate.createFile(tablePath);

		if (!createFile) {
			System.out.println("System error, exit");
			System.exit(0);
			return false;
		}

		try {
			FileOutputStream fileOutputStream = new FileOutputStream(tablePath);
			StringBuilder table_header = new StringBuilder();
			table_header.append(DbController.HEADER_INFO);
			for (int i = 0; i < columnsInfo.length; i++) {
				table_header.append(columnsInfo[i][0] + DbController.INTERVAL_INFO);
			}
			table_header.append(DbController.END_INFO + "\n");

			StringBuilder tableTypes = new StringBuilder();
			tableTypes.append(DbController.HEADER_INFO);
			for (int i = 0; i < columnsInfo.length; i++) {
				tableTypes.append(columnsInfo[i][1] + DbController.INTERVAL_INFO);
			}
			tableTypes.append(DbController.END_INFO + "\n");

			StringBuilder tableExtra = new StringBuilder();
			tableExtra.append(DbController.HEADER_INFO);
			for (int i = 0; i < columnsInfo.length; i++) {
				if (columnsInfo[i][2] == "") {
					columnsInfo[i][2] = "Nothing";
				}
				tableExtra.append(columnsInfo[i][2] + DbController.INTERVAL_INFO);
			}
			tableExtra.append(DbController.END_INFO + "\n");
			table_header.append(tableTypes).append(tableExtra);
			fileOutputStream.write(table_header.toString().getBytes());
			fileOutputStream.close();
			return true;
		} catch (Exception e) {
			System.err.println("System error, exit");
			System.exit(0);
			return false;
		}
	}
}
